﻿using CommunityToolkit.Mvvm.ComponentModel;
using CommunityToolkit.Mvvm.Input;
using CommunityToolkit.Mvvm.Messaging;
using GameView.Comment;
using GameView.Models;
using GameView.Services;
using GameView.Services.Comment;
using GameView.Services.Dtos.Project;
using GameView.Services.Dtos.RechargesDto;
using GameView.Services.Enums;
using MaterialDesignThemes.Wpf;
using System.Collections.ObjectModel;
using System.ComponentModel.DataAnnotations;
using System.Diagnostics.CodeAnalysis;

namespace GameView.ViewModels
{
    public partial class RechargeAddNewViewModel : ObservableValidator, IRecipient<RechargeRecodeMsg>, IRecipient<NotificationMsg>
    {
        private string rav = "Rravv";
        private List<ProjectWithGamesInfo> _projectWithGamesInfos;
        private readonly RechargeService _service;
        private readonly ProjectService _projectService;
        private readonly IMessenger _messenger;

        public RechargeAddNewViewModel(RechargeService service, ProjectService projectService, IMessenger messenger)
        {
            _service = service;
            _messenger = messenger;
            _messenger.RegisterAll(this);
            _projectService = projectService;
            var _tcpClientService = ExtentHelper.GetService<HPSocketTcpClientService>();
            IsMerchant = StaticValues.LoginInfo.PersonInfo.RoleId != 3;
            LoadPG().ConfigureAwait(false);
            var json = SecureStorage.Load(rav);
            if (!json.IsNullOrEmpty())
                BaseSuggestions = JSON.Deserialize<List<RavvMode>>(json);
            if (!BaseSuggestions.IsNullOrEmpty())
            {
                Suggestions = new ObservableCollection<RavvMode>(BaseSuggestions);
            }
        }

        [ObservableProperty]
        private bool _isLoading = false;

        private List<RavvMode> BaseSuggestions { get; } = [];

        [ObservableProperty]
        private ObservableCollection<RavvMode> _suggestions = [];

        [ObservableProperty]
        private string? _autoSuggestText;

        [ObservableProperty]
        private bool _isDialog = true;

        [ObservableProperty]
        private ObservableCollection<TreeNode> _nodes = [];

        [ObservableProperty]
        private bool _isIncreaseSelected = true; // 默认选中"增加"

        [ObservableProperty]
        private bool _isDecreaseSelected = false;

        [ObservableProperty]
        [NotifyDataErrorInfo]
        [Required(ErrorMessage = "选择游戏")]
        private TreeNode? _selectedNode;

        [ObservableProperty]
        [NotifyDataErrorInfo]
        [Required(ErrorMessage = "请选择收货人角色")]
        private int _recivertRole = 7002;

        [ObservableProperty]
        [NotifyDataErrorInfo]
        [NotifyCanExecuteChangedFor(nameof(SubmitCommand))]
        [Required(ErrorMessage = "角色名称不能为空")]
        [NotNull]
        private string _characterName = string.Empty;

        [ObservableProperty]
        [NotifyCanExecuteChangedFor(nameof(SubmitCommand))]
        private string _projectName = string.Empty;

        [ObservableProperty]
        [NotifyCanExecuteChangedFor(nameof(SubmitCommand))]
        private string _gameName = string.Empty;

        [ObservableProperty]
        [NotifyDataErrorInfo]
        [NotifyCanExecuteChangedFor(nameof(SubmitCommand))]
        [NotNull]
        [Range(1, 999999999, ErrorMessage = "充值金额必须在1-999999999之间")]
        private uint? _rechargeAmount = null;

        [ObservableProperty]
        private string _rechargeAmountStr = string.Empty;

        [ObservableProperty]
        private bool _isMerchant = true;

        [ObservableProperty]
        private string _searchStr = "";

        [RelayCommand]
        private async Task RefreshList()
        {
            await LoadPG();
        }

         partial void OnSearchStrChanged(string value)
        {
            // 属性变更时自动执行搜索
            Search();
        }

        [RelayCommand]
        private void Search()
        {
            Nodes.Clear();
            List<TreeNode> psInit = [];
            foreach (var data in _projectWithGamesInfos)
            {
                var p = new TreeNode() { IsParent = true, Id = data.Id, Name = data.Name, Type = 0 };
                foreach (var game in data.Games)
                    psInit.Add(new() { IsParent = false, Parent = p, Type = 1, Id = game.Id, Name = game.Name, Status = (int)game.Status });
            }
            List<TreeNode> ps = [];
            if (SearchStr.IsNullOrEmpty())
                ps = psInit;
            else
                ps = psInit.FindAll(q => q.Name.Contains(SearchStr));
            foreach (var pi in ps)
            {
                Nodes.Add(pi);
            }
        }

        private async Task<bool> LoadPG()
        {
            try
            {
                IsLoading = true;
                ApiResponse<List<ProjectWithGamesInfo>> res = new();
                if (StaticValues.LoginInfo.PersonInfo.RoleId != 1)
                    res = await _projectService.GetByPersonIdHAsync();
                else
                    res = await _projectService.GetAllHAsync();
                if (res.Data.IsNullOrEmpty())
                    return false;
                _projectWithGamesInfos = res.Data;
                Nodes.Clear();
                if (IsMerchant)
                {
                    foreach (var data in _projectWithGamesInfos)
                    {
                        var p = new TreeNode() { IsParent = true, Id = data.Id, Name = data.Name, Type = 0 };
                        Nodes.Add(p);
                        foreach (var game in data.Games)
                            p.Children.Add(new() { IsParent = false, Parent = p, Type = 1, Id = game.Id, Name = game.Name, Status = (int)game.Status });
                    }
                }
                else
                {
                    foreach (var data in _projectWithGamesInfos)
                    {
                        var p = new TreeNode() { IsParent = true, Id = data.Id, Name = data.Name, Type = 0 };
                        foreach (var game in data.Games)
                            Nodes.Add(new() { IsParent = false, Parent = p, Type = 1, Id = game.Id, Name = game.Name, Status = (int)game.Status });
                    }
                }
                //GlobalMessage.Instance.ShowInformation($"大区列表已刷新！");

                return true;
            }
            catch (Exception ex)
            {
                GlobalMessage.Instance.ShowError($"操作失败：{ex.Message}");
                return false;
            }
            finally
            {
                IsLoading = false;
            }
        }

        [RelayCommand]
        private void SelectedItemChanged(TreeNode value)
        {
            if (value is null)
                return;
            if (value.Parent == null)
            {
                ProjectName = value.Name;
                GameName = "";
                return;
            }
            SelectedNode = value;
            if (SelectedNode.Status == 6002)
            {
                GlobalMessage.Instance.ShowWarning($"{SelectedNode.Name}已经离线，无法操作！");
                return;
            }
            ProjectName = value.Parent.Name;
            GameName = value.Name;
        }

        [RelayCommand(CanExecute = nameof(CanSubmit))]
        private async Task Submit()
        {
            int.TryParse(RechargeAmountStr, out var resAmount);
            var dto = new RechargeAddDto
            {
                ProjectName = SelectedNode?.Parent.Name,
                GameName = SelectedNode?.Name,
                RecivertRole = RecivertRole,
                CharacterName = CharacterName,
                ChangeType = IsDecreaseSelected ? 4002 : 4001,
                RechargeAmount = resAmount,
            };
            CharacterName = "";
            RechargeAmountStr = "";
            //if (!BaseSuggestions.Any(q => q.CName == dto.CharacterName))
            //{
            //    while (BaseSuggestions.Count() > 30)
            //        BaseSuggestions.RemoveAt(0);
            //    BaseSuggestions.Add(new RavvMode(dto.ProjectName, dto.GameName, dto.CharacterName));
            //    SecureStorage.Save(rav, JSON.Serialize(BaseSuggestions));
            //}

            // TODO: 调用服务层提交数据
            // await _rechargeService.AddAsync(dto);
            var res = await _service.AddNewAsync(dto);
            if (res == null)
            {
                GlobalMessage.Instance.ShowError($"网络异常请稍后核查充值结果！");
            }
            if (res.StatusCode == 200)
            {
                // 关闭弹窗
                if (IsDialog)
                    DialogHost.CloseDialogCommand.Execute(null, null);
                else
                {
                    CharacterName = "";
                    RechargeAmount = 0;
                }
                _messenger.Send(new RechargeRecodeMsg(res.Data, "add"));
                //GlobalMessage.Instance.ShowSuccess("操作成功！");
            }
            else
            {
                GlobalMessage.Instance.ShowError($"操作失败：{res.Errors}");
            }
        }

         partial void OnRechargeAmountStrChanged(string value)
        {
            if (uint.TryParse(value, out var res))
                RechargeAmount = res;
            else
                RechargeAmount = 0;
        }

        private bool CanSubmit() => !HasErrors && SelectedNode != null && SelectedNode.Parent != null && SelectedNode.Status == 6001 && RechargeAmount >= 1 && !CharacterName.IsNullOrEmpty();

         partial void OnAutoSuggestTextChanged(string? oldValue, string? newValue)
        {
            try
            {
                if (!string.IsNullOrWhiteSpace(newValue))
                {
                    CharacterName = newValue;

                    if (BaseSuggestions.IsNullOrEmpty())
                        return;
                    var searchResult = BaseSuggestions.Where(x => IsMatch(x.CName, newValue));
                    if (searchResult.Count() == 1)
                    {
                        var f = searchResult.First();

                        if (IsMerchant)
                        {
                            var et = Nodes.FirstOrDefault(q => q.Name == f.PName);
                            if (et == null)
                                return;
                            var cn = et.Children.FirstOrDefault(q => q.Name == f.GName);
                            if (cn != null)
                                SelectedNode = cn;
                        }
                        else
                        {
                            var et = Nodes.FirstOrDefault(q => q.Name == f.GName);
                            if (et != null)
                                SelectedNode = et;
                        }
                        ProjectName = f.PName;
                        GameName = f.GName;
                    }
                    Suggestions = new(searchResult);
                }
                else
                {
                    CharacterName = "";
                    Suggestions = new(BaseSuggestions);
                }
            }
            catch (Exception ex)
            {
                GlobalMessage.Instance.ShowError(ex.Message);
            }
        }

        private static bool IsMatch(string item, string currentText)
        {
            return item.Contains(currentText, StringComparison.OrdinalIgnoreCase);
        }

        public void Receive(RechargeRecodeMsg message)
        {
            if (message.Source != "fList")
                return;
            var rr = message.Value;
            if (IsMerchant)
            {
                var et = Nodes.FirstOrDefault(q => q.Name == rr.ProjectName);
                if (et == null)
                    return;
                var cn = et.Children.FirstOrDefault(q => q.Name == rr.GameName);
                if (cn != null)
                    SelectedNode = cn;
            }
            else
            {
                var et = Nodes.FirstOrDefault(q => q.Name == rr.GameName);
                if (et != null)
                    SelectedNode = et;
            }
            ProjectName = rr.ProjectName;
            GameName = rr.GameName;
            CharacterName = rr.CharacterName;
        }

        public async void Receive(NotificationMsg message)
        {
            if (message == null || message.Value == null || message.Value.Type <= 0)
                return;
            if (message.Value.Type != 1205 && message.Value.Type != 1204)
                return;
            var strs = message.Value.Content.Split("-");
            await System.Windows.Application.Current.Dispatcher.InvokeAsync(() =>
        {
            TreeNode tn = new();
            TreeNode pTn = new();

            if (!IsMerchant)
            {
                tn = Nodes?.FirstOrDefault(q => q.Name == strs[1]);
            }
            else
            {
                pTn = Nodes?.FirstOrDefault(q => q.Name == strs[0]);
                if (pTn == null)
                    return;
                tn = pTn.Children?.FirstOrDefault(q => q.Name == strs[1]);
            }
            if (tn == null)
            {
                _ = LoadPG();
                return;
            }
            var pWG = _projectWithGamesInfos.Find(q => q.Name == tn.Parent.Name);

            GameStatus gs = message.Value.Type == 1205 ? GameStatus.OffLine : GameStatus.OneLine;

            tn.Status = (int)gs;
            var p = pWG?.Games?.FirstOrDefault(q => q.Name == tn.Name);
            if (p != null)
                p.Status = gs;
        });
        }
    }

    public class RavvMode
    {
        public RavvMode()
        {
        }

        public RavvMode(string p, string g, string c)
        {
            PName = p;
            GName = g;
            CName = c;
        }

        public string PName { get; set; }
        public string GName { get; set; }
        public string CName { get; set; }
        public string SName => $"{CName}({PName})";
    }
}